//#include "types.h"
#include "semaphore.h"
//#include "user.h"
#define TSTACKSIZE 4096

struct semaphore* s;
int sem_init_value;

void* beginthread() {

  int pid, tid, i;
   
  pid = thread_getProcId();
  tid = thread_getid();
  
  while (1) {
      sem_down(s);
	  for (i = 0; i < 3; i++) {
		printf(1, "THREAD: Process %d Thread %d is running, semvalue = %d threads in cs = %d.\n", pid, tid, s->value, sem_init_value-(s->value));
	  }  
      sem_up(s);
	printf(1, "THREAD: Process %d Thread %d is left sem, semvalue = %d threads in cs = %d.\n", pid, tid, s->value, sem_init_value-(s->value));
      sleep(1);
  }
  
  thread_exit(0);
}

int
main(int argc, char *argv[])
{

  int n, i, tid;
  void* tstack;
  
  if(argc <= 2){
    printf(1, "usage: %s <threads count> <semaphore init value>\n", argv[0]);
    exit();
  }
  
  n = atoi(argv[1]);
  sem_init_value = atoi(argv[2]);
  
  if (n <= 0 || sem_init_value < 0) {
    printf(1, "usage: %s <threads count> <semaphore init value>\n", argv[0]);
    exit();  
  }
  
  s = semaphore_create(sem_init_value);
  
  if (s < 0) {
    printf(1, "MAIN: no semaphore available\n");
    exit();
  } else {
  	printf(1, "MAIN: semaphore acquired\n");
  }
  
  for(i = 0; i < n; i++) {
    tstack = malloc(TSTACKSIZE);

    if (tstack > 0) {
  		tid = thread_create(beginthread, tstack, TSTACKSIZE);
  		printf(1, "MAIN: spawned thread = %d\n", tid);
  	} else {
  		printf(1, "MAIN: malloc failed, only spawned %d out of %d threads.\n", i, n);
  		break;
  	}
  	
  }
  
  while (1) {
  	//wait for threads indefintely
  }
  
  free(s);
  
  exit();
}
